package io.gitee.itxinmeng.encrypt.spring.boot.common.encrypt.strategy.impl;

import cn.hutool.core.lang.Assert;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.json.JSONUtil;
import io.gitee.itxinmeng.encrypt.spring.boot.autoconfigure.properties.EncryptProperties;
import io.gitee.itxinmeng.encrypt.spring.boot.common.encrypt.EncryptMethodFactory;
import io.gitee.itxinmeng.encrypt.spring.boot.common.encrypt.strategy.IEncryptStrategy;
import io.gitee.itxinmeng.encrypt.spring.boot.db.AppAuth;
import io.gitee.itxinmeng.encrypt.spring.boot.db.DbUtils;
import io.gitee.itxinmeng.encrypt.spring.boot.util.ServletUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.nio.charset.StandardCharsets;


/**
 * @author mx
 *
 */
@Component
@ConditionalOnProperty(prefix = "custom.encrypt", name = "method", havingValue = "SIGN_AND_AES")
public class SignAndAesEncryptStrategyImpl implements IEncryptStrategy, InitializingBean {
    private static final Logger LOGGER = LoggerFactory.getLogger(SignAndAesEncryptStrategyImpl.class);

    @Resource
    private EncryptProperties config;

    @Override
    public Object encryptBody(Object body, ServerHttpRequest request) {
        try {
            String content = JSONUtil.toJsonStr(body);
            byte[] data = content.getBytes();
            String respStr = "";
            // Aes 加密
            String appKey = ServletUtil.getHeader(request.getHeaders(),"appKey");
            Assert.notBlank(appKey,"appKey can not be empty！");
            AppAuth appAuth = DbUtils.findAppAuthByAppKey(appKey);

            Assert.notNull(appAuth,"The appKey are not exist!");
            Assert.notBlank(appAuth.getAppSecret(),"The appKey are not exist!");
            respStr = SecureUtil.aes(appAuth.getAppSecret().getBytes(config.getCharset()))
                    .encryptHex(data);
            if (LOGGER.isDebugEnabled()) {
                LOGGER.info("Before encrypt：({})，After encrypt：({})", content, respStr);
            }
            return respStr;
        } catch (Exception e) {
            LOGGER.error("Encrypt reponse error!", e);
            throw new RuntimeException(e.getMessage());
        }
    }

    @Override
    public String decryptBody(HttpHeaders headers,String content) {
        String appKey = ServletUtil.getHeader(headers,"appKey");
        Assert.notBlank(appKey,"appKey can not be empty！");
        AppAuth appAuth = DbUtils.findAppAuthByAppKey(appKey);
        Assert.notNull(appAuth,"The appKey are not exist!");
        Assert.notBlank(appAuth.getAppSecret(),"The appKey are not exist!");
        Assert.isTrue(ServletUtil.checkSign(headers,appAuth.getAppSecret()),"Sign check fail");
        String decryptContent = SecureUtil.aes(appAuth.getAppSecret().getBytes(StandardCharsets.UTF_8))
                .decryptStr(content);
        return decryptContent;
    }

    @Override
    public void afterPropertiesSet() {
        EncryptMethodFactory.INSTANCE.addEncryptStrategy(EncryptMethodFactory.EncryptMethodEnum.SIGN_AND_AES,this);
    }
}
